//Nathan Popham
//4003-573-01: Procedural Shading
//Lab 4: Task 3 
//
//mybrickbump
// Bumpmaps a surface with a pattern of 1x1, 1x2, and 2x2 blocks. A predefined
// 5x5 pattern of these blocks is repeated across the surface. The mortar
// is set to an indented groove, while a "turbulence" noise function is applied
// to the bricks themselves. 
//
// tilewidth    -   width of each tile (1x1 block is one tile)
// tileheight   -   height of each tile 
// mortarwidth  -   thickness of the mortar between blocks
// octaves      -   octaves for brick noise (set -1.0 for no noise)
// lacunity     -   lacunity of brick noise function
// gain         -   gain of brick noise function
// groovedepth  -   depth of mortar groove as factor of mortarwidth

#define snoise(x) (2*noise(x)-1)


//function described in Advanced Renderman by Apodaca & Gritz
// p. 253
float turbulence(point p; uniform float octaves, lacunarity, gain)
{
    varying float sum = 0, amp = 1;
    varying point pp = p;
    uniform float i;

    for(i = 0; i < octaves; i += 1)
    {
        sum += amp * abs(snoise(pp));
        amp *= gain; pp *= lacunarity;
    }
    return sum;
}


displacement
mybrickbump (   float tilewidth = 2.0;
                float tileheight = 2.0;
                float mortarwidth = 0.2;
                float octaves = 6.0;
                float lacunity = 2.0;
                float gain = .8;
                float groovedepth = 1.0;
)
{
    float sqr(float x) { return x * x; }

    float numTilesWidth = 5.0;
    float numTilesHeight = 5.0;

    float TwoDIndex(float x, y, width) { return (x + y * width); }

    //unfortunately have to hardcode the array size
    //a 3.0 represents a tile with top and left mortar border
    //a 2.0 is a tile with only top mortar border
    //a 1.0 is a tile with only left mortar border
    //a 0.0 is a tile with no mortar borders
    float template[25.0] = 
        { 
            3.0, 2.0, 3.0, 3.0, 2.0,
            3.0, 3.0, 1.0, 3.0, 2.0,
            1.0, 3.0, 2.0, 3.0, 3.0,
            3.0, 2.0, 3.0, 1.0, 3.0,
            1.0, 0.0, 3.0, 2.0, 1.0
        };
     
    
    float is = (1.0 - s);
    float it = t;

    float brickColumn = floor(is*numTilesWidth - .0001);
    float brickRow = floor(it*numTilesHeight - .0001);
    float brickx = mod(is*numTilesWidth*tilewidth, tilewidth);
    float bricky = mod(it*numTilesHeight*tileheight, tileheight);
    
    float borderInfo = template[TwoDIndex(brickColumn, brickRow, numTilesWidth)];
   

    //if in brick
    if((borderInfo == 2.0 || borderInfo == 0.0 || brickx > mortarwidth) && 
       (borderInfo == 1.0 || borderInfo == 0.0 || bricky > mortarwidth))
    {
        N = calculatenormal(P - turbulence(P, octaves, lacunity, gain)*normalize(N));
    }
    else//in mortar
    {
        float amp = 0.0;

        if((borderInfo == 1.0 || borderInfo == 3.0) && brickx < mortarwidth)
        {
            amp = groovedepth*(-sqr(-brickx + sqrt(mortarwidth)) + mortarwidth);
        }
        else //in mortar on top
        {
            amp = groovedepth*(-sqr(-bricky + sqrt(mortarwidth)) + mortarwidth);
        }


        N = calculatenormal(P + amp*normalize(N));
    }
}


